/*
 * Copyright (c) 2007 Apple Inc. All rights reserved.
 */
/*
 * FILE_ID: thread_status.h
 */


#ifndef _ARM_THREAD_STATUS_H_
#define _ARM_THREAD_STATUS_H_

#include <mach/arm/_structs.h>
#include <mach/message.h>
#include <mach/arm/thread_state.h>

/*
 *    Support for determining the state of a thread
 */


/*
 *  Flavors
 */

#define ARM_THREAD_STATE		1
#define ARM_UNIFIED_THREAD_STATE ARM_THREAD_STATE
#define ARM_VFP_STATE			2
#define ARM_EXCEPTION_STATE		3
#define ARM_DEBUG_STATE			4 /* pre-armv8 */
#define THREAD_STATE_NONE		5
#define ARM_THREAD_STATE64		6
#define ARM_EXCEPTION_STATE64	7
// ARM_THREAD_STATE_LAST (legacy) 8
#define ARM_THREAD_STATE32		9

/* API */
#define ARM_DEBUG_STATE32		14
#define ARM_DEBUG_STATE64		15
#define ARM_NEON_STATE			16
#define ARM_NEON_STATE64		17


#define VALID_THREAD_STATE_FLAVOR(x)\
((x == ARM_THREAD_STATE) 		||	\
 (x == ARM_VFP_STATE) 			||	\
 (x == ARM_EXCEPTION_STATE) 	||	\
 (x == ARM_DEBUG_STATE) 		||	\
 (x == THREAD_STATE_NONE)		||  \
 (x == ARM_THREAD_STATE32)		||	\
 (x == ARM_THREAD_STATE64)		||	\
 (x == ARM_EXCEPTION_STATE64)	||	\
 (x == ARM_NEON_STATE)		||	\
 (x == ARM_NEON_STATE64)		||	\
 (x == ARM_DEBUG_STATE32) 		||	\
 (x == ARM_DEBUG_STATE64))

struct arm_state_hdr {
    uint32_t flavor;
    uint32_t count;
};
typedef struct arm_state_hdr arm_state_hdr_t;

typedef _STRUCT_ARM_THREAD_STATE		arm_thread_state_t;
typedef _STRUCT_ARM_THREAD_STATE		arm_thread_state32_t;
typedef _STRUCT_ARM_THREAD_STATE64		arm_thread_state64_t;

struct arm_unified_thread_state {
	arm_state_hdr_t ash;
	union {
		arm_thread_state32_t ts_32;
		arm_thread_state64_t ts_64;
	} uts;
};
#define	ts_32	uts.ts_32
#define	ts_64	uts.ts_64
typedef struct arm_unified_thread_state arm_unified_thread_state_t;

#define ARM_THREAD_STATE_COUNT ((mach_msg_type_number_t) \
   (sizeof (arm_thread_state_t)/sizeof(uint32_t)))
#define ARM_THREAD_STATE32_COUNT ((mach_msg_type_number_t) \
   (sizeof (arm_thread_state32_t)/sizeof(uint32_t)))
#define ARM_THREAD_STATE64_COUNT ((mach_msg_type_number_t) \
   (sizeof (arm_thread_state64_t)/sizeof(uint32_t)))
#define ARM_UNIFIED_THREAD_STATE_COUNT ((mach_msg_type_number_t) \
   (sizeof (arm_unified_thread_state_t)/sizeof(uint32_t)))


typedef _STRUCT_ARM_VFP_STATE			arm_vfp_state_t;
typedef _STRUCT_ARM_NEON_STATE			arm_neon_state_t;
typedef _STRUCT_ARM_NEON_STATE			arm_neon_state32_t;
typedef _STRUCT_ARM_NEON_STATE64		arm_neon_state64_t;

typedef _STRUCT_ARM_EXCEPTION_STATE		arm_exception_state_t;
typedef _STRUCT_ARM_EXCEPTION_STATE		arm_exception_state32_t;
typedef _STRUCT_ARM_EXCEPTION_STATE64	arm_exception_state64_t;

typedef arm_thread_state_t  arm_saved_state_t;

typedef _STRUCT_ARM_DEBUG_STATE32		arm_debug_state32_t;
typedef _STRUCT_ARM_DEBUG_STATE64		arm_debug_state64_t;

/*
 * Otherwise not ARM64 kernel and we must preserve legacy ARM definitions of
 * arm_debug_state for binary compatability of userland consumers of this file.
 */
#if defined(__arm__)
typedef _STRUCT_ARM_DEBUG_STATE			arm_debug_state_t;
#elif defined(__arm64__)
typedef _STRUCT_ARM_LEGACY_DEBUG_STATE		arm_debug_state_t;
#else
#error Undefined architecture
#endif

#define ARM_VFP_STATE_COUNT ((mach_msg_type_number_t) \
   (sizeof (arm_vfp_state_t)/sizeof(uint32_t)))

#define ARM_EXCEPTION_STATE_COUNT ((mach_msg_type_number_t) \
   (sizeof (arm_exception_state_t)/sizeof(uint32_t)))

#define ARM_EXCEPTION_STATE64_COUNT ((mach_msg_type_number_t) \
   (sizeof (arm_exception_state64_t)/sizeof(uint32_t)))

#define ARM_DEBUG_STATE_COUNT ((mach_msg_type_number_t) \
   (sizeof (arm_debug_state_t)/sizeof(uint32_t)))

#define ARM_DEBUG_STATE32_COUNT ((mach_msg_type_number_t) \
   (sizeof (arm_debug_state32_t)/sizeof(uint32_t)))

#define ARM_DEBUG_STATE64_COUNT ((mach_msg_type_number_t) \
   (sizeof (arm_debug_state64_t)/sizeof(uint32_t)))

#define ARM_NEON_STATE_COUNT ((mach_msg_type_number_t) \
   (sizeof (arm_neon_state_t)/sizeof(uint32_t)))

#define ARM_NEON_STATE64_COUNT ((mach_msg_type_number_t) \
   (sizeof (arm_neon_state64_t)/sizeof(uint32_t)))

#define MACHINE_THREAD_STATE 		ARM_THREAD_STATE
#define MACHINE_THREAD_STATE_COUNT	ARM_UNIFIED_THREAD_STATE_COUNT

/*
 * Largest state on this machine:
 */
#define THREAD_MACHINE_STATE_MAX	THREAD_STATE_MAX

static inline void *saved_state64(void *iss)
{
    return iss;
}

#endif    /* _ARM_THREAD_STATUS_H_ */
